#include <iostream>
#include <string>
#include <functional>
#include <vector>
#include <time.h>
#include <unistd.h>
#include <pthread.h>

// typedef std::function<void()> func_t;//等同于下一个语句
using func_t = std::function<void()>;//C++11标准，需要头文件functional

const int threadnum = 5;//创建5个线程

class ThreadData
{
public:
    ThreadData(const std::string &name, const uint64_t &ctime, func_t f)
        : threadname(name), createtime(ctime), func(f)
    {
    }

public:
    std::string threadname;//线程名字
    uint64_t createtime;//创建的时间
    func_t func;
};

void Print()
{
    std::cout << "我是线程执行的大任务的一部分" << std::endl;
}

// 新线程
void *ThreadRoutine(void *args)
{
    int a = 10;
    ThreadData *td = static_cast<ThreadData *>(args);
    while (true)
    {
        std::cout << "new thread"
                  << " thread name: " << td->threadname << " create time: " << td->createtime << std::endl;
        td->func();
        //if(td->threadname == "thread-4")
        //{
        //    std::cout << td->threadname << " 触发了异常!!!!!" << std::endl;
        //    a /= 0; // 故意制作异常，可以发现一个线程出了异常而退出会导致整个进程退出
        //}
        sleep(1);
    }
}

// 主线程
int main()
{
    std::vector<pthread_t> pthreads;
    for (size_t i = 0; i < threadnum; i++)//创建多线程
    {
        char threadname[64];
        snprintf(threadname, sizeof(threadname), "%s-%lu", "thread", i);

        pthread_t tid;
        ThreadData *td = new ThreadData(threadname, (uint64_t)time(nullptr), Print);
        pthread_create(&tid, nullptr, ThreadRoutine, td);//第一个参数是输出型参数，返回获得的线程id，第二个参数是线程的属性，一般设置为nullptr
        //第三个参数是新线程要执行的方法，而主线程继续向下运行，第四个参数是想要传递给新线程（threadroutine函数）的参数，本身是（void*）
        //也就是说第四个参数可以传结构体对象/对象的指针
        pthreads.push_back(tid);//保存tid，便于后续打印
        sleep(1);
    }
    std::cout << "thread id: ";
    for(const auto &tid: pthreads)
    {
        std::cout << tid << ",";
    }

    std::cout << std::endl;


    while (true)
    {
        std::cout << "main thread" << std::endl;
        sleep(3);
    }
}
